package com.tcxhb.job.core.schedule.workflow.retry;

import com.tcxhb.job.core.schedule.workflow.FlowHandler;
import com.tcxhb.job.dao.dataobject.JobInstanceDO;
import com.tcxhb.job.common.constants.BaseException;
import com.tcxhb.job.common.constants.CommonErrorCode;
import com.tcxhb.job.common.constants.enums.ExecuteStatus;
import com.tcxhb.job.common.constants.enums.ScheduleStatus;
import com.tcxhb.job.common.model.MiscResult;
import com.tcxhb.job.core.schedule.execute.JobRunContext;
import com.tcxhb.job.core.service.job.AgentApiService;
import com.tcxhb.job.core.service.job.JobInstanceService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;

/**
 * @Description:
 * @Auther: tcxhb
 * @Date: 2023/11/16
 */
@Component
public class JobRetryCheckFlow implements FlowHandler<JobRunContext> {
    @Autowired
    private JobInstanceService instanceService;

    @Autowired
    private AgentApiService agentApiService;

    @Override
    public MiscResult handle(JobRunContext context) {
        JobInstanceDO instanceDO = instanceService.queryById(context.getReq().getInstanceId());
        //不需要重试了
        if (!needRetry(context, instanceDO)) {
            JobInstanceDO update = new JobInstanceDO();
            update.setId(instanceDO.getId());
            update.setRetryFlag(0);
            instanceService.updateById(update);
            throw new BaseException("1001", "不需要重试了:"+instanceDO.getId());
        }
        //校验客户端任务状态
        if (checkAgentJobStatus(instanceDO) != null) {
            throw new BaseException(CommonErrorCode.JOB_STATUS_ERROR);
        }
        // 返回结果
        context.setInstanceList(Arrays.asList(instanceDO));
        context.setAppName(instanceDO.getAppName());
        context.setRunStrategy(instanceDO.getRunStrategy());
        return MiscResult.suc();
    }

    /**
     * 校验客户端的设备状态
     *
     * @param instanceDO
     * @return
     */
    private Integer checkAgentJobStatus(JobInstanceDO instanceDO) {
        if (StringUtils.isBlank(instanceDO.getMachineAddr())) {
            return null;
        }
        // 从机器上获取状态
        MiscResult<Integer> result = agentApiService.status(instanceDO);
        if (result.getData() == null) {
            return null;
        }
        // 不是失败的状态都是成功的
        Integer status = result.getData();
        if (!ExecuteStatus.FAIL.eq(status)) {
            JobInstanceDO update = new JobInstanceDO();
            update.setId(instanceDO.getId());
            update.setExecuteStatus(status);
            update.setScheduleStatus(ScheduleStatus.SUCC.getType());
            instanceService.updateById(update);
            return status;
        }
        return null;
    }

    /**
     * 是否需要重试
     *
     * @param context
     * @param instanceDO
     * @return
     */
    private Boolean needRetry(JobRunContext context, JobInstanceDO instanceDO) {
        Integer scheduleStatus = instanceDO.getScheduleStatus();
        Integer executeStatus = instanceDO.getExecuteStatus();
        //跑一次返回成功
        if (context.getReq().getRunOnce()) {
            return true;
        }
        //大于重试次数
        if (instanceDO.getFailCount() > instanceDO.getRunStrategy().getRetryCount()) {
            return false;
        }
        //运行失败,或者调度失败需要重跑
        if (ScheduleStatus.FAIL.eq(scheduleStatus) || ExecuteStatus.FAIL.eq(executeStatus)) {
            return true;
        }
        return false;
    }
}
